package promote.brozen.algorithm.linked;

import lombok.Getter;
import lombok.Setter;

/**
 * @author Brozen
 * @date 2020/1/13 6:51 PM
 */
public class Linked<K> {

    private LinkedNode<K> head;

    private LinkedNode<K> tail;

    private transient int size;

    public Linked() {
        this.head = new LinkedNode<>(null);
        this.tail = new LinkedNode<>(null);
    }

    public void addHead(K key) {
        LinkedNode<K> node = new LinkedNode<>(key);
        if (this.head.next != null) {
            // 头结点后继节点存在，链表非空，需要插入
            this.head.next.prev = node;
            node.next = this.head.next;
            node.prev = this.head;
            this.head.next = node;
        } else {// 后继节点不存在，链表为空，需要设置尾节点指向
            this.head.next = node;
            node.prev = this.head;
            node.next = this.tail;
            this.tail.prev = node;
        }
    }

    public void addTail(K key) {
        LinkedNode<K> node = new LinkedNode<>(key);
        if (this.tail.prev != null) {// 尾节点的前驱节点存在，则说明链表非空
            this.tail.prev.next = node;
            node.prev = this.tail.prev;
            node.next = this.tail;
            this.tail.prev = node;
        } else {// 前驱节点不存在，链表为空，需要设置头结点指向
            this.head.next = node;
            node.prev = this.head;
            node.next = this.tail;
            this.tail.prev = node;
        }
    }

    public LinkedNode<K> getFirstNode() {
        return this.head.next;
    }

    public K getFirst() {
        LinkedNode<K> firstNode = getFirstNode();
        return firstNode == null ? null : firstNode.value;
    }

    public LinkedNode<K> getLastNode() {
        return this.tail.prev;
    }

    public K getLast() {
        LinkedNode<K> lastNode = getLastNode();
        return lastNode == null ? null : lastNode.value;
    }

    public void remove(K key) {
        LinkedNode<K> node = findNode(key);
        if (node == null) {
            return;
        }

    }

    public void removeNode(LinkedNode<K> node) {
        node.prev.next = node.next;
        node.next.prev = node.prev;
        node.next = null;
        node.prev = null;
        node.value = null;
    }

    private LinkedNode<K> findNode(K key) {
        LinkedNode<K> node = getFirstNode();
        while (node != null && node != this.tail) {
            if (node.getValue().equals(key)) {
                return node;
            }
            node = node.next;
        }
        return null;
    }

    @Getter
    @Setter
    public static class LinkedNode<K> {

        private K value;

        private LinkedNode<K> prev;

        private LinkedNode<K> next;

        LinkedNode(K value) {
            this.value = value;
        }
    }

}
